home *** CD-ROM | disk | FTP | other *** search
/ Gekikoh Dennoh Club 5 / Gekikoh Dennoh Club Vol. 5 (Japan).7z / Gekikoh Dennoh Club Vol. 5 (Japan) (Track 01).bin / internet / xip / iijppp.lzh / src / chap.c < prev    next >
C/C++ Source or Header  |  1994-10-10  |  6KB  |  258 lines

  1. /*
  2.  *            PPP CHAP Module
  3.  *
  4.  *        Written by Toshiharu OHNO (tony-o@iij.ad.jp)
  5.  *
  6.  *   Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation,
  11.  * advertising materials, and other materials related to such
  12.  * distribution and use acknowledge that the software was developed
  13.  * by the Internet Initiative Japan, Inc.  The name of the
  14.  * IIJ may not be used to endorse or promote products derived
  15.  * from this software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  *
  20.  *    TODO:
  21.  *        o Imprement retransmission timer.
  22.  */
  23. #include "fsm.h"
  24. #include "chap.h"
  25. #include "lcpproto.h"
  26. #include "lcp.h"
  27. #include "hdlc.h"
  28. #include "phase.h"
  29. #include "vars.h"
  30.  
  31. static int chapid;
  32.  
  33. static char *chapcodes[] = {
  34.   "???", "CHALLENGE", "RESPONCE", "SUCCESS", "FAILURE"
  35. };
  36.  
  37. extern char *AuthGetSecret();
  38.  
  39. void
  40. ChapOutput(code, id, ptr, count)
  41. u_int code, id;
  42. u_char *ptr;
  43. int count;
  44. {
  45.   int plen;
  46.   struct fsmheader lh;
  47.   struct mbuf *bp;
  48.  
  49.   plen =  sizeof(struct fsmheader) + count;
  50.   lh.code = code;
  51.   lh.id = id;
  52.   lh.length = htons(plen);
  53.   bp = mballoc(plen, MB_FSM);
  54.   bcopy(&lh, MBUF_CTOP(bp), sizeof(struct fsmheader));
  55.   if (count)
  56.     bcopy(ptr, MBUF_CTOP(bp) + sizeof(struct fsmheader), count);
  57. #ifdef DEBUG
  58.   DumpBp(bp);
  59. #endif
  60.   LogPrintf(LOG_LCP, "ChapOutput: %s\n", chapcodes[code]);
  61.   HdlcOutput(PRI_NORMAL, PROTO_CHAP, bp);
  62. }
  63.  
  64.  
  65. static char challenge_data[80];
  66. static int  challenge_len;
  67.  
  68. void
  69. SendChapChallenge()
  70. {
  71.   int keylen, len, i;
  72.   char *cp;
  73.  
  74.   srandom(time(NULL));
  75.   ++chapid;
  76.  
  77.   cp = challenge_data;
  78.   *cp++ = challenge_len = random() % 32 + 16;
  79.   for (i = 0; i < challenge_len; i++)
  80.     *cp++ = random() & 0xff;
  81.   len = strlen(VarAuthName);
  82.   bcopy(VarAuthName, cp, len);
  83.   cp += len;
  84.   ChapOutput(CHAP_CHALLENGE, chapid, challenge_data, cp - challenge_data);
  85. }
  86.  
  87. #ifdef DEBUG
  88. void
  89. DumpDigest(mes, cp, len)
  90. char *mes;
  91. char *cp;
  92. {
  93.   int i;
  94.  
  95.   logprintf("%s: ", mes);
  96.   for (i = 0; i < len; i++) {
  97.     logprintf(" %02x", *cp++ & 0xff);
  98.   }
  99.   logprintf("\n");
  100. }
  101. #endif
  102.  
  103. void
  104. RecvChapTalk(chp, bp)
  105. struct fsmheader *chp;
  106. struct mbuf *bp;
  107. {
  108.   int valsize, len;
  109.   int arglen, keylen, namelen;
  110.   char *cp, *argp, *ap, *name, *digest;
  111.   char *keyp;
  112.   MD5_CTX context;                            /* context */
  113.   char answer[100];
  114.   char cdigest[16];
  115.  
  116.   len = ntohs(chp->length);
  117. #ifdef DEBUG
  118.   logprintf("length: %d\n", len);
  119. #endif
  120.   arglen = len - sizeof(struct fsmheader);
  121.   cp = (char *)MBUF_CTOP(bp);
  122.   valsize = *cp++ & 255;
  123.   name = cp + valsize;
  124.   namelen = arglen - valsize - 1;
  125.   name[namelen] = 0;
  126.   LogPrintf(LOG_PHASE, " Valsize = %d, Name = %s\n", valsize, name);
  127.  
  128.   /*
  129.    * Get a secret key corresponds to the peer
  130.    */
  131.   keyp = AuthGetSecret(SECRETFILE, name, namelen, chp->code == CHAP_RESPONSE);
  132.  
  133.   switch (chp->code) {
  134.   case CHAP_CHALLENGE:
  135.     if (keyp) {
  136.       keylen = strlen(keyp);
  137.     } else {
  138.       keylen = strlen(VarAuthKey);
  139.       keyp = VarAuthKey;
  140.     }
  141.     name = VarAuthName;
  142.     namelen = strlen(VarAuthName);
  143.     argp = malloc(1 + valsize + namelen);
  144.     digest = argp;
  145.     *digest++ = 16;        /* value size */
  146.     ap = answer;
  147.     *ap++ = chp->id;
  148.     bcopy(keyp, ap, keylen);
  149.     ap += keylen;
  150.     bcopy(cp, ap, valsize);
  151. #ifdef DEBUG
  152.     DumpDigest("recv", ap, valsize);
  153. #endif
  154.     ap += valsize;
  155.     MD5Init(&context);
  156.     MD5Update(&context, answer, ap - answer);
  157.     MD5Final(digest, &context);
  158. #ifdef DEBUG
  159.     DumpDigest("answer", digest, 16);
  160. #endif
  161.     bcopy(name, digest + 16, namelen);
  162.     ap += namelen;
  163.     /* Send answer to the peer */
  164.     ChapOutput(CHAP_RESPONSE, chp->id, argp, namelen + 17);
  165.     break;
  166.   case CHAP_RESPONSE:
  167.     if (keyp) {
  168.       /*
  169.        * Compute correct digest value
  170.        */
  171.       keylen = strlen(keyp);
  172.       ap = answer;
  173.       *ap++ = chp->id;
  174.       bcopy(keyp, ap, keylen);
  175.       ap += keylen;
  176.       MD5Init(&context);
  177.       MD5Update(&context, answer, ap - answer);
  178.       MD5Update(&context, challenge_data+1, challenge_len);
  179.       MD5Final(cdigest, &context);
  180. #ifdef DEBUG
  181.       DumpDigest("got", cp, 16);
  182.       DumpDigest("expect", cdigest, 16);
  183. #endif
  184.       /*
  185.        * Compare with the response
  186.        */
  187.       if (bcmp(cp, cdigest, 16) == 0) {
  188.     ChapOutput(CHAP_SUCCESS, chp->id, "Wellcome!!", 10);
  189.     NewPhase(PHASE_NETWORK);
  190.     break;
  191.       }
  192.     }
  193.     /*
  194.      * Peer is not registerd, or response digest is wrong.
  195.      */
  196.     ChapOutput(CHAP_FAILURE, chp->id, "Invalid!!", 9);
  197.     LcpClose();
  198.     break;
  199.   }
  200. }
  201.  
  202. void
  203. RecvChapResult(chp, bp)
  204. struct fsmheader *chp;
  205. struct mbuf *bp;
  206. {
  207.   int len;
  208.   struct lcpstate *lcp = &LcpInfo;
  209.  
  210.   len = ntohs(chp->length);
  211. #ifdef DEBUG
  212.   logprintf("length: %d\n", len);
  213. #endif
  214.   if (chp->code == CHAP_SUCCESS) {
  215.     if (lcp->auth_iwait == PROTO_CHAP) {
  216.       lcp->auth_iwait = 0;
  217.       if (lcp->auth_ineed == 0)
  218.     NewPhase(PHASE_NETWORK);
  219.     }
  220.   } else {
  221.     /*
  222.      * Maybe, we shoud close LCP. Of cause, peer may take close action, too.
  223.      */
  224.     ;
  225.   }
  226. }
  227.  
  228. void
  229. ChapInput(struct mbuf *bp)
  230. {
  231.   int len = plength(bp);
  232.   struct fsmheader *chp;
  233.  
  234.   if (len >= sizeof(struct fsmheader)) {
  235.     chp = (struct fsmheader *)MBUF_CTOP(bp);
  236.     if (len >= ntohs(chp->length)) {
  237.       if (chp->code < 1 || chp->code > 4)
  238.     chp->code = 0;
  239.       LogPrintf(LOG_LCP, "ChapInput: %s\n", chapcodes[chp->code]);
  240.  
  241.       bp->offset += sizeof(struct fsmheader);
  242.       bp->cnt -= sizeof(struct fsmheader);
  243.  
  244.       switch (chp->code) {
  245.       case CHAP_CHALLENGE:
  246.       case CHAP_RESPONSE:
  247.     RecvChapTalk(chp, bp);
  248.     break;
  249.       case CHAP_SUCCESS:
  250.       case CHAP_FAILURE:
  251.     RecvChapResult(chp, bp);
  252.     break;
  253.       }
  254.     }
  255.   }
  256.   pfree(bp);
  257. }
  258.